package com.study.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration3 extends WebSecurityConfigurerAdapter {

    //@Override
    //protected void configure(HttpSecurity http) throws Exception {
    //    http
    //            .authorizeRequests()
    //            .antMatchers("/product/**").hasAuthority("USER")
    //            .antMatchers("/admin/**").hasAuthority("ADMIN")
    //            .anyRequest().authenticated()
    //            .and()
    //            .formLogin().and()
    //            .httpBasic();
    //}
    /*上面的代码是访问默认的登录界面，现在要改成下面的自己的login.html*/

    //@Autowired
    //private UsersServiceImpl usersService;
    @Autowired
    private PersistentTokenRepository tokenRepository;

    @Autowired
    private UserDetailsService userDetailsService;

    //@Autowired//处理403  返回json请求
    //private MyAccessDeniedHandle myAccessDeniedHandler;


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //处理403  有2种方式，先返回json看看，再跳转页面
        http
                .exceptionHandling()
                //.accessDeniedHandler(myAccessDeniedHandler);   //返回json请求
                .accessDeniedPage("/403Page");// 返回页面 只适用非前端框架的方式，适用于同步请求方式，所有异步使用AccessDeniedHandler
        // 开启记住我功能
        http
                .rememberMe()
                .tokenRepository(tokenRepository)
                .userDetailsService(userDetailsService)
                //.tokenValiditySeconds(120)  //设置失效时间
        ;
        http
            .formLogin()
                .loginPage("/toLoginPage")
                .loginProcessingUrl("/login")
                .defaultSuccessUrl("/login")
                .failureUrl("/unauth")
                .permitAll()
                .and()
            .authorizeRequests()
                .antMatchers("/", "/toLoginPage").permitAll()
                .antMatchers("/login/**").permitAll()//静态资源放行！！！！！！
                .antMatchers("/product/**").hasAuthority("USER")
                .antMatchers("/admin/**").hasAuthority("ADMIN")
                //下面这一行一定是写在antMatchers后面
                .anyRequest().authenticated()

                //todo 这个异常处理虽然简单但是没生效
                //.and()
                //.exceptionHandling().accessDeniedPage("/unauth")

                //todo 下面是比较较复杂的异常处理
                //.and()
                //.exceptionHandling()
                //// 认证异常处理handler 使用的 lambda的内部的实现
                //.authenticationEntryPoint((request,response,authenticationException)->{
                //    Map<String,Object> rs = new HashMap<>();
                //    rs.put("code",401);
                //    rs.put("msg","尚未认证!");
                //    ObjectMapper objectMapper = new ObjectMapper();
                //    String json = objectMapper.writeValueAsString(rs);
                //    response.setStatus(200);
                //    response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
                //    response.getWriter().println(json);
                //
                //})
                // 授权异常处理handler 使用的 lambda的内部的实现
                //.and()
                //.accessDeniedHandler((request,response,accessDeniedException)->{
                //    Map<String,Object> rs = new HashMap<>();
                //    rs.put("code",401);
                //    rs.put("msg","没有权限!");
                //    ObjectMapper objectMapper = new ObjectMapper();
                //    String json = objectMapper.writeValueAsString(rs);
                //    response.setStatus(200);
                //    response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
                //    response.getWriter().println(json);
                //})
                .and()
            .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/toLoginPage")//登出成功的话，跳转路径
                .permitAll()
                //下面csrf建议关闭，如果不关，那么只有get请求能用，其他请求统统都是403
                .and()
            .csrf().disable();

        ;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth.userDetailsService(userDetailsService)// 设置自定义的userDetailsService
                .passwordEncoder(passwordEncoder());

    }


    @Bean
    public PasswordEncoder passwordEncoder() {
        //为了演示方便，我们使用NoOpPasswordEncoder（这个就是不加密）
        return NoOpPasswordEncoder.getInstance();
    }


}